﻿// -----------------------------------------------------------------------
// <copyright file="DslUtil.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Rosieks.VisualStudio.Web.Flow.CustomCode
{
    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Shell;
    using Microsoft.VisualStudio.Shell.Interop;
    using Rosieks.VisualStudio.Web.Flow.Interop;
    using OLE = Microsoft.VisualStudio.OLE.Interop;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class WebflowUtil
    {
        public static IVsHierarchy GetSelectedHierarchy()
        {
            return WebflowUtil.GetSelectedHierarchy(WebflowPackage.Instance);
        }

        public static IVsHierarchy GetSelectedHierarchy(IServiceProvider serviceProvider)
        {
            IVsHierarchy objectForIUnknown = null;
            if (serviceProvider != null)
            {
                IVsMonitorSelection service = WebflowUtil.GetService<IVsMonitorSelection>(serviceProvider);
                if (service == null)
                {
                    return objectForIUnknown;
                }

                uint maxValue = uint.MaxValue;
                IVsMultiItemSelect ppMIS = null;
                IntPtr zero = IntPtr.Zero;
                IntPtr ppSC = IntPtr.Zero;
                service.GetCurrentSelection(out zero, out maxValue, out ppMIS, out ppSC);
                if (ppSC != IntPtr.Zero)
                {
                    Marshal.Release(ppSC);
                }

                if ((zero != IntPtr.Zero && ((int)zero) != -1) && ((int)zero) != -2)
                {
                    objectForIUnknown = Marshal.GetObjectForIUnknown(zero) as IVsHierarchy;
                    Marshal.Release(zero);
                }
            }

            return objectForIUnknown;
        }

        public static TInterface GetService<TInterface>() where TInterface : class
        {
            return WebflowUtil.GetService<TInterface>(WebflowPackage.Instance);
        }

        public static TInterface GetService<TInterface>(IServiceProvider serviceProvider) where TInterface : class
        {
            try
            {
                return serviceProvider.GetService(typeof(TInterface)) as TInterface;
            }
            catch
            {
                return default(TInterface);
            }
        }

        public static TInterface CreateSitedInstance<TInterface>(OLE.IServiceProvider serviceProvider, Guid clsid) where TInterface : class
        {
            return WebflowUtil.CreateSitedInstance<TInterface>(new ServiceProvider(serviceProvider), clsid);
        }

        public static TInterface CreateSitedInstance<TInterface>(IServiceProvider serviceProvider, Guid clsid) where TInterface : class
        {
            TInterface local = WebflowUtil.CreateInstance<TInterface>(serviceProvider, clsid);
            if (local == null)
            {
                return null;
            }

            OLE.IObjectWithSite site = local as OLE.IObjectWithSite;
            OLE.IServiceProvider service = WebflowUtil.GetService<OLE.IServiceProvider>(serviceProvider);
            if (site != null && service != null)
            {
                site.SetSite(service);
                return local;
            }

            return default(TInterface);
        }

        private static TInterface CreateInstance<TInterface>(IServiceProvider serviceProvider, Guid clsid) where TInterface : class
        {
            TInterface objectForIUnkown = default(TInterface);
            if (clsid != Guid.Empty)
            {
                ILocalRegistry service = WebflowUtil.GetService<ILocalRegistry>(serviceProvider);
                if (service == null)
                {
                    return objectForIUnkown;
                }

                IntPtr zero = IntPtr.Zero;
                Guid riid = NativeMethods.IID_IUnknown;
                try
                {
                    service.CreateInstance(clsid, null, ref riid, 1, out zero);
                }
                catch
                {
                }

                if (zero == IntPtr.Zero)
                {
                    return objectForIUnkown;
                }

                try
                {
                    objectForIUnkown = Marshal.GetObjectForIUnknown(zero) as TInterface;
                }
                catch
                {
                }

                try
                {
                    Marshal.Release(zero);
                }
                catch
                {
                }
            }

            return objectForIUnkown;
        }
    }
}
